#include "EventAddDialog.h"

#include "GroupEntry.h"

#include <libintl.h>
#define _(String) gettext(String)

/* EventAddDialog 对象的信号 */
static guint add_dialog_signal[ADD_DIALOG_SIGNAL_END];
static guint old_index = __UINT32_MAX__;

struct _EventAddDialog
{
	AdwDialog parent_instance;
	//
	GtkCheckButton *is_important_button;
	AdwEntryRow    *name_entry_row;
	AdwEntryRow    *describe_entry_row;
	AdwComboRow    *group_select_combo;
	GtkCalendar    *end_time_calendar;
	AdwAlertDialog *apply_dialog;
	AdwAlertDialog *delete_dialog;
	GtkButton      *apply_button;
	//
	AdwPreferencesGroup *select_combo_preference;
	AdwPreferencesGroup *delete_event_row;
	/* 与该弹窗相关的 EventEntry 条目 */
	EventEntry *relate_entry;
	/* 可用组 */
	ObjectArray *usable_group_array;
	/* 是否是修改条目的 Dialog */
	bool is_modify;
};

G_DEFINE_FINAL_TYPE(EventAddDialog, event_add_dialog, ADW_TYPE_DIALOG)

static void
clean_combo_old_index(AdwDialog *self, gpointer)
{
	old_index = __UINT32_MAX__;
}

/* 将 EventAddDialog 参数设置到对应的 EventEntry 条目 */
static void
set_up_to_relate_event_entry(EventAddDialog *self)
{
	time_t set_time;
	if (!self->relate_entry)
		return;
	event_entry_set_event_name(
		self->relate_entry,
		gtk_editable_get_text(GTK_EDITABLE(self->name_entry_row)));
	event_entry_set_event_describe(
		self->relate_entry,
		gtk_editable_get_text(GTK_EDITABLE(self->describe_entry_row)));
	event_entry_set_is_important(
		self->relate_entry,
		(bool)gtk_check_button_get_active(self->is_important_button));
	set_time = g_date_time_to_unix(
		gtk_calendar_get_date(self->end_time_calendar));
	event_entry_set_end_time(self->relate_entry, set_time);
}

static void
real_apply_add_dialog_cb(AdwAlertDialog *alert, gchar *response,
			 EventAddDialog *dialog)
{
	if (g_str_equal(response, "cancel"))
		return;
	if (dialog->is_modify) {
		set_up_to_relate_event_entry(dialog);
		event_entry_emit_signal(dialog->relate_entry,
					EVENT_ENTRY_SIGNAL_MODIFY);
	} else {
		g_signal_emit(dialog, add_dialog_signal[ADD_DIALOG_NEW_EVENT],
			      0);
	}
	adw_dialog_close(ADW_DIALOG(dialog));
}

/* 按下 Apply 按钮 */
static void
apply_add_dialog_cb(EventAddDialog *self, gpointer data)
{
	adw_dialog_present(ADW_DIALOG(self->apply_dialog), GTK_WIDGET(self));
}

static void
real_delete_add_dialog_cb(AdwAlertDialog *alert, gchar *response,
			  EventAddDialog *dialog)
{
	if (g_str_equal(response, "cancel"))
		return;
	event_entry_emit_signal(dialog->relate_entry,
				EVENT_ENTRY_SIGNAL_REMOVE);
	adw_dialog_close(ADW_DIALOG(dialog));
}

/* 按下删除按钮 */
static void
delete_add_dialog_cb(EventAddDialog *self, gpointer data)
{
	adw_dialog_present(ADW_DIALOG(self->delete_dialog), GTK_WIDGET(self));
}

void
event_add_dialog_set_default_template(EventAddDialog *self, EventEntry *entry)
{
	static char buffer[20];
	struct tm  *time_struct;
	time_t	    appoint_time;

	g_return_if_fail(self != NULL && entry != NULL);
	self->is_modify	   = true;
	self->relate_entry = entry;
	adw_dialog_set_title(ADW_DIALOG(self), _("Modify Event"));

	if (event_entry_get_is_important(entry))
		gtk_check_button_set_active(self->is_important_button, true);
	else
		gtk_check_button_set_active(self->is_important_button, false);

	gtk_editable_set_text(GTK_EDITABLE(self->name_entry_row),
			      event_entry_get_event_name(entry));
	gtk_editable_set_text(GTK_EDITABLE(self->describe_entry_row),
			      event_entry_get_event_describe(entry));

	gtk_widget_set_visible(GTK_WIDGET(self->select_combo_preference),
			       false);
	gtk_widget_set_visible(GTK_WIDGET(self->delete_event_row), true);

	sprintf(buffer, "GroupID: %07d", event_entry_get_group_id(entry));
	adw_action_row_set_subtitle(ADW_ACTION_ROW(self->group_select_combo),
				    buffer);
	gtk_widget_set_sensitive(GTK_WIDGET(self->group_select_combo), false);

	appoint_time = event_entry_get_end_time(entry);
	time_struct  = localtime(&appoint_time);
	gtk_calendar_set_year(self->end_time_calendar,
			      time_struct->tm_year + 1900);
	gtk_calendar_set_month(self->end_time_calendar, time_struct->tm_mon);
	gtk_calendar_set_day(self->end_time_calendar, time_struct->tm_mday);
}

static void
change_group_id_in_combo_cb(AdwComboRow *self, GtkStateFlags flags,
			    EventAddDialog *dialog)
{
	GroupEntry  *group_entry;
	EventString *info_str;
	guint	     index;

	index = adw_combo_row_get_selected(self);
	if (old_index == index)
		return;
	else
		old_index = index;

	group_entry = GROUP_ENTRY(
		object_array_get_with_index(dialog->usable_group_array, index));
	info_str = event_string_new("GroupID: ");
	if (group_entry) {
		event_string_append(info_str,
				    group_entry_get_group_id_str(group_entry));
	}
	adw_action_row_set_subtitle(ADW_ACTION_ROW(self), ES_GET(info_str));
	event_object_unref(info_str);
}

void
event_add_dialog_take_usable_group(EventAddDialog *self,
				   ObjectArray	  *usable_group_array)
{
	GtkStringList *string_list;
	GroupEntry    *group_entry;

	if (!self)
		goto return_with_unref_source;

	/* 没有可用组则无法添加新事件 */
	if (!usable_group_array) {
		gtk_widget_set_sensitive(GTK_WIDGET(self->apply_button), false);
		gtk_widget_set_sensitive(GTK_WIDGET(self->is_important_button),
					 false);
		gtk_widget_set_sensitive(GTK_WIDGET(self->name_entry_row),
					 false);
		gtk_widget_set_sensitive(GTK_WIDGET(self->describe_entry_row),
					 false);
		adw_preferences_row_set_title(
			ADW_PREFERENCES_ROW(self->group_select_combo),
			_("No available groups"));
		gtk_widget_set_sensitive(GTK_WIDGET(self->group_select_combo),
					 false);
		return;
	}

	self->usable_group_array = usable_group_array;
	//
	string_list = gtk_string_list_new(NULL);
	object_array_iteration_reset(usable_group_array);
	group_entry =
		(GroupEntry *)object_array_iteration_get(usable_group_array);
	while (group_entry) {
		gtk_string_list_append(string_list,
				       group_entry_get_group_name(group_entry));
		group_entry = (GroupEntry *)object_array_iteration_get(
			usable_group_array);
	}
	adw_combo_row_set_model(self->group_select_combo,
				G_LIST_MODEL(string_list));
	change_group_id_in_combo_cb(self->group_select_combo, 0, self);

	return;
return_with_unref_source:
	event_object_unref(usable_group_array);
}

const char *
event_add_dialog_get_group_name(EventAddDialog *self)
{
	GroupEntry *group_entry;
	guint	    select_index;
	g_return_val_if_fail(self != NULL, NULL);
	select_index = adw_combo_row_get_selected(self->group_select_combo);
	group_entry  = GROUP_ENTRY(object_array_get_with_index(
		 self->usable_group_array, select_index));
	if (!group_entry)
		return NULL;
	return group_entry_get_group_name(group_entry);
}

euint32
event_add_dialog_get_group_id(EventAddDialog *self)
{
	GroupEntry *group_entry;
	guint	    select_index;
	g_return_val_if_fail(self != NULL, 0);
	select_index = adw_combo_row_get_selected(self->group_select_combo);
	group_entry  = GROUP_ENTRY(object_array_get_with_index(
		 self->usable_group_array, select_index));
	if (!group_entry)
		return 0;
	return group_entry_get_group_id(group_entry);
}

time_t
event_add_dialog_get_end_time(EventAddDialog *self)
{
	g_return_val_if_fail(self != NULL, 0L);
	return g_date_time_to_unix(
		gtk_calendar_get_date(self->end_time_calendar));
}

const char *
event_add_dialog_get_event_name(EventAddDialog *self)
{
	g_return_val_if_fail(self != NULL, NULL);
	return gtk_editable_get_text(GTK_EDITABLE(self->name_entry_row));
}

const char *
event_add_dialog_get_event_describe(EventAddDialog *self)
{
	g_return_val_if_fail(self != NULL, NULL);
	return gtk_editable_get_text(GTK_EDITABLE(self->describe_entry_row));
}

bool
event_add_dialog_get_is_important(EventAddDialog *self)
{
	g_return_val_if_fail(self != NULL, false);
	return (bool)gtk_check_button_get_active(self->is_important_button);
}

static void
event_add_dialog_finalize(GObject *object)
{
	event_object_unref(EVENT_ADD_DIALOG(object)->usable_group_array);
	G_OBJECT_CLASS(event_add_dialog_parent_class)->finalize(object);
}

static void
event_add_dialog_class_init(EventAddDialogClass *klass)
{
	GObjectClass   *object_class = G_OBJECT_CLASS(klass);
	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);

	gtk_widget_class_set_template_from_resource(
		widget_class, "/org/korack/event/ui/EventAddDialog.ui");
	gtk_widget_class_bind_template_child(widget_class, EventAddDialog,
					     is_important_button);
	gtk_widget_class_bind_template_child(widget_class, EventAddDialog,
					     name_entry_row);
	gtk_widget_class_bind_template_child(widget_class, EventAddDialog,
					     describe_entry_row);
	gtk_widget_class_bind_template_child(widget_class, EventAddDialog,
					     group_select_combo);
	gtk_widget_class_bind_template_child(widget_class, EventAddDialog,
					     end_time_calendar);
	gtk_widget_class_bind_template_child(widget_class, EventAddDialog,
					     select_combo_preference);
	gtk_widget_class_bind_template_child(widget_class, EventAddDialog,
					     delete_event_row);
	gtk_widget_class_bind_template_child(widget_class, EventAddDialog,
					     apply_dialog);
	gtk_widget_class_bind_template_child(widget_class, EventAddDialog,
					     apply_button);
	gtk_widget_class_bind_template_child(widget_class, EventAddDialog,
					     delete_dialog);
	gtk_widget_class_bind_template_callback(widget_class,
						clean_combo_old_index);
	gtk_widget_class_bind_template_callback(widget_class,
						apply_add_dialog_cb);
	gtk_widget_class_bind_template_callback(widget_class,
						real_apply_add_dialog_cb);
	gtk_widget_class_bind_template_callback(widget_class,
						delete_add_dialog_cb);
	gtk_widget_class_bind_template_callback(widget_class,
						real_delete_add_dialog_cb);
	gtk_widget_class_bind_template_callback(widget_class,
						change_group_id_in_combo_cb);

	add_dialog_signal[ADD_DIALOG_NEW_EVENT] = g_signal_newv(
		"new-event", G_TYPE_FROM_CLASS(object_class),
		G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
		NULL, NULL, NULL, NULL, G_TYPE_NONE, 0, NULL);

	G_OBJECT_CLASS(klass)->finalize = event_add_dialog_finalize;
}

static void
event_add_dialog_init(EventAddDialog *self)
{
	gtk_widget_init_template(GTK_WIDGET(self));
	self->is_modify		 = false;
	self->relate_entry	 = NULL;
	self->usable_group_array = NULL;
}

EventAddDialog *
event_add_dialog_new(void)
{
	return g_object_new(EVENT_TYPE_ADD_DIALOG, NULL);
}
